package com.hmall.order.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmall.feign.client.ItemClient;
import com.hmall.feign.client.UserClient;
import com.hmall.feign.dto.Address;
import com.hmall.feign.dto.Item;
import com.hmall.feign.utils.UserHolder;
import com.hmall.order.constant.OrderMQConstant;
import com.hmall.order.mapper.OrderDetailMapper;
import com.hmall.order.mapper.OrderLogisticsMapper;
import com.hmall.order.mapper.OrderMapper;
import com.hmall.order.pojo.*;
import com.hmall.order.service.IOrderService;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;

/**
 * 订单-业务层-实现
 */
@Slf4j
@Service
public class OrderService extends ServiceImpl<OrderMapper, Order> implements IOrderService {
    @Autowired(required = false)
    private OrderDetailMapper orderDetailMapper;
    /**
     * 物流信息
     */
    @Autowired(required = false)
    private OrderLogisticsMapper orderLogisticsMapper;
    @Autowired(required = false)
    private ItemClient itemClient;
    @Autowired(required = false)
    private UserClient userClient;


    /**
     * RabbitMQ
     */
    @Autowired
    private RabbitTemplate rabbitTemplate;

    //Seata分布式事务注解
    @GlobalTransactional
    @Override
    public Long createOrder(OrderDTO orderDTO) {
        //1）根据雪花算法生成订单id
        Order order = new Order();

        //2）商品微服务提供FeignClient，实现根据id查询商品的接口
        //3）根据itemId查询商品信息
        Item item = getItemById(orderDTO.getItemId());

        //4）基于商品价格、购买数量计算商品总价：totalFee
        BigDecimal totalFee = calculateTotalFee(orderDTO.getNum(), item);
        order.setTotalFee(totalFee);

        //5）封装Order对象，初识status为未支付
        //注意：订单的状态，1、未付款 2、已付款,未发货 3、已发货,未确认 4、确认收货，交易成功 5、交易取消，订单关闭 6、交易结束，已评价
        order.setStatus(1);

        //补全信息
        order.setPaymentType(orderDTO.getPaymentType());
        order.setUserId(getUserId());
        //创建时间
        order.setCreateTime(new Date());
        //由于没有接入支付，现在先直接假定，创建订单时，就已经支付
        order.setPayTime(new Date());
        //更新时间
        order.setUpdateTime(new Date());

        //6）将Order写入数据库tb_order表中
        baseMapper.insert(order);

        //7）将商品信息、orderId信息封装为OrderDetail对象，写入tb_order_detail表
        OrderDetail orderDetail = new OrderDetail();

        orderDetail.setOrderId(order.getId());
        orderDetail.setItemId(item.getId());
        orderDetail.setNum(orderDTO.getNum());
        orderDetail.setName(item.getName());
        orderDetail.setPrice(item.getPrice());
        orderDetail.setSpec(item.getSpec());
        orderDetail.setImage(item.getImage());
        orderDetail.setCreateTime(new Date());
        orderDetail.setUpdateTime(new Date());

        orderDetailMapper.insert(orderDetail);

        //8）将user-service的根据id查询地址接口封装为FeignClient
        //9）根据addressId查询user-service服务，获取地址信息
        Address address = getAddressById(orderDTO.getAddressId());

        //10）将地址封装为OrderLogistics对象，写入tb_order_logistics表
        OrderLogistics orderLogistics = new OrderLogistics();
        orderLogistics.setOrderId(order.getId());
        orderLogistics.setLogisticsNumber("");
        orderLogistics.setLogisticsCompany("");
        orderLogistics.setContact(address.getContact());
        orderLogistics.setMobile(address.getMobile());
        orderLogistics.setProvince(address.getProvince());
        orderLogistics.setCity(address.getCity());
        orderLogistics.setTown(address.getTown());
        orderLogistics.setStreet(address.getStreet());
        orderLogistics.setCreateTime(new Date());
        orderLogistics.setUpdateTime(new Date());

        orderLogisticsMapper.insert(orderLogistics);

        //11）在item-service提供减库存接口，并编写FeignClient
        //12）调用item-service的减库存接口
        reduceItemStockNum(item.getId(), orderDTO.getNum());

        //定时关单
        rabbitTemplate.convertAndSend(
                OrderMQConstant.ORDER_EXCHANGE,
                OrderMQConstant.ORDER_ROUTING_KEY,
                order.getId()
        );

        return order.getId();
    }

    /**
     * 减少商品的库存
     *
     * @param itemId 商品Id
     * @param num    要减少的库存数量
     */
    private void reduceItemStockNum(Long itemId, Integer num) {
        // 通过Feign远程调用商品服务，减少库存
        itemClient.reduceItemStockNum(itemId,num);
        log.info("订单微服务，减少库存，商品Id => " + itemId + "，减少数量：" + num);
    }


    /**
     * 调用商品微服务，查询商品信息
     */
    private Item getItemById(Long itemId) {
        // 远程调用获取
        return itemClient.getItemById(itemId);
    }

    /**
     * 根据地址Id，查询地址信息
     */
    private Address getAddressById(Long addressId) {
        // 通过远程调用用户服务，查询用户的地址信息
        return userClient.getAddressById(addressId);
    }

    /**
     * 计算商品总价
     *
     * @param num  商品数量
     * @param item 商品信息
     */
    private BigDecimal calculateTotalFee(int num, Item item) {
        //数量
        BigDecimal numBigDecimal = new BigDecimal(num);
        //单价
        BigDecimal singlePrice = new BigDecimal(item.getPrice());
        //算法：计算总金额（单价 * 每个商品的数量 = 总金额）
        return singlePrice.multiply(numBigDecimal);
    }

    /**
     * 获取当前登录的用户Id
     */
    private Long getUserId() {
        // 从UserHolder获取用户ID
        return UserHolder.getUser();
    }
}